package com.tengju.user.application.archives;

import com.google.common.collect.Lists;
import com.tengju.user.application.archives.dto.BatchStarUpdateDTO;
import com.tengju.user.domain.model.sign.*;
import com.tengju.user.domain.model.star.StarUserFeatureRepository;
import com.tengju.user.domain.model.user.*;
import com.tengju.user.domain.service.UserDocService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class StarManageService {

    private final UserInfoRepository userInfoRepository;
    private final StarLimitRepository starLimitRepository;
    private final UserDocService userDocService;
    private final StarChangeRecordRepository starChangeRecordRepository;
    private final StarUserFeatureRepository starUserFeatureRepository;
    private final StarSignInfoRepository starSignInfoRepository;
    private final StarContractRepository starContractRepository;

    public void batchUpdateStar(BatchStarUpdateDTO batchStarUpdateDTO, Staff staff) {
        List<Long> idCodeList = batchStarUpdateDTO.getIdCodeList();
        List<UserInfo> userInfos = userDocService.searchUserByIdCodes(
                idCodeList.stream()
                        .filter(Objects::nonNull)
                        .map(UserIdCode::new)
                        .collect(Collectors.toList())
        );
        if (CollectionUtils.isEmpty(userInfos)) {
            return;
        }
        Integer targetStarRole = batchStarUpdateDTO.getTargetStarRole();
        Integer targetStarLevel = batchStarUpdateDTO.getTargetStarLevel();
        for (UserInfo userInfo : userInfos) {
            tryUpdateStar(userInfo, targetStarRole, targetStarLevel, StarChangeTypeEnum.HANDLE, staff,false);
        }
    }

    /**
     * 更改星级
     * 2. 记录星级变更记录
     * 3. 变更星级等级
     *
     * @param userInfo
     * @param targetStarRole
     * @param targetStarLevel
     * @param changeTypeEnum
     * @param staff
     */
    @Transactional(value = "dealerTransactionManager", rollbackFor = Exception.class)
    public void tryUpdateStar(UserInfo userInfo,
                              Integer targetStarRole,
                              Integer targetStarLevel,
                              StarChangeTypeEnum changeTypeEnum,
                              Staff staff,
                              boolean isAdd) {
        if (!isAdd) {
            StarSignInfo starSignInfo = starSignInfoRepository.getByIdCode(userInfo.getIdCode());
            if (starSignInfo != null && !starSignInfo.getStep().equals(StarSignStepEnum.END.getStep())) {
                throw new StarSignException("用户已经在签约流程中，请先终止签约流程再修改！");
            }
        }
        doUpdateStar(userInfo,targetStarRole,targetStarLevel,changeTypeEnum,staff);
    }

    @Transactional(value = "dealerTransactionManager", rollbackFor = Exception.class)
    public void doUpdateStar(UserInfo userInfo,
                             Integer targetStarRole,
                             Integer targetStarLevel,
                             StarChangeTypeEnum changeTypeEnum,
                             Staff staff) {
        StarChangeRecord starChangeRecord = new StarChangeRecord(
                userInfo,
                targetStarRole,
                targetStarLevel,
                changeTypeEnum,
                staff
        );
        UserIdCode idCode = userInfo.getIdCode();
        userInfo.updateStar(targetStarRole, targetStarLevel);
        userInfoRepository.insertOrUpdateStarInfo(userInfo.getIdCode(), userInfo.getStarRole(), userInfo.getStarLevel());
        //后台运营手动修改等级，添加白名单防止自动降回去
        if (StarChangeTypeEnum.HANDLE.equals(changeTypeEnum)) {
            starLimitRepository.addWhiteUser(idCode, staff.getName());
        }
        starChangeRecordRepository.saveStarChangeRecord(starChangeRecord);
    }

    public void updateUserStarFeature(StarChangeEvent starChangeEvent) {
        UserIdCode idCode = UserIdCode.of(starChangeEvent.getIdCode());
        StarLevelEnum starLevel = StarLevelEnum.parseByCode(starChangeEvent.getAfterStarLevel());
        starUserFeatureRepository.insertOrUpdateStarLevel(idCode,starLevel,starChangeEvent.getUpdateBy());
    }

    @Transactional(value = "dealerTransactionManager", rollbackFor = Exception.class)
    public void batchInvalid(List<Long> idCodes, Staff staff) {
        for (Long idCode : idCodes) {
            log.info("注销用户星级身份:{}",idCode);
            UserInfo userInfo = userInfoRepository.getByIdCode(UserIdCode.of(idCode));
            if (userInfo == null || StarLevelEnum.NONE.getCode().equals(userInfo.getStarLevel())) {
                continue;
            }
            StarContractInfo existStarContractInfo = starContractRepository.getByIdCodeAndType(UserIdCode.of(idCode), userInfo.getStarRole());
            //星级等级改为经销商
            tryUpdateStar(userInfo,
                    StarRoleEnum.NONE.getCode(),
                    StarLevelEnum.NONE.getCode(),
                    StarChangeTypeEnum.HANDLE,
                    staff,
                    false);
            if (existStarContractInfo != null) {
                //失效原本的合同数据
                existStarContractInfo.invalid();
                starContractRepository.update(existStarContractInfo);
            }
        }
    }

}
